#    This file is part of robo-ircbot.
#
#    robo-ircbot is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    robo-ircbot is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with robo-ircbot.  If not, see <http://www.gnu.org/licenses/>.

package App::Modular::Module::DownloadModule;
use strict;
use warnings;
use File::Copy;
use Cwd qw(abs_path);
use File::Fetch;
use base qw(App::Modular::Module);

print ":: DownloadModule module loaded.\n";

# Events we want to receive.
sub events { return "PRIVMSG"; }

sub help {
        return (
                "Administrative module downloading.",
                ".lsmod           List all loaded modules.",
                ".getmod <url>    Download a module and load it.",
                ".repmod <url>    Download a module and replace existing, then load.",
                ".unload <module> Unload a module.",
                ".load <module>   Load a module."
        );
}

# PRIVMSG events.
sub event_privmsg
{
        shift;
        my $e = shift;

        my $auth = $e->robo->mod("Auth") || return;
        my $help = $e->robo->mod("Helper") || return;

        # Admin commands.
        if ($auth->is_authed($e->from)) {
                my $path = abs_path($0); $path =~ s/(.+\/).+/$1/;

                # lsmod
                if ($e->data eq ".lsmod") {
                        my @mods = $e->robo->{mod}->{mod}->modules();
                        $e->s("PRIVMSG ".$e->dest." :\002lsmod\002: ".join(" ", @mods));
                # getmod
                } elsif ($e->data =~ /^\.getmod (http:\/\/[\w\d\._\-\/]+\.pm)$/) {
                        down_mod($1, $path, $e, 0, "getmod");
                # repmod
                } elsif ($e->data =~ /^\.repmod (http:\/\/[\w\d\._\-\/]+\.pm)$/) {
                        down_mod($1, $path, $e, 1, "repmod");
                # delmod
                } elsif ($e->data =~ /^\.delmod ([\w\d\._\-]+)$/) {
                        my $file_name = $1;
                        if (-e $path."modules/".$file_name.".pm") {
                                if (unlink($path."modules/".$file_name.".pm")) {
                                        $e->s("PRIVMSG ".$e->dest." :\002delmod\002: Deleted ".$file_name." from modules directory and unloaded.");
                                        $e->robo->{mod}->unload_module($file_name);
                                } else {
                                        $e->s("PRIVMSG ".$e->dest." :\002delmod\002: Could not delete ".$file_name." from modules directory.  Please contact your neighborhood's haxor.");
                                }
                        } else {
                                $e->s("PRIVMSG ".$e->dest." :\002delmod\002: Cannot delete! Module does not exist!");
                        }
                # unload
                } elsif ($e->data =~ /^\.unload ([\w\d]+)$/) {
                        if ($e->robo->{mod}->unload_module($1)) {
                                $e->s("PRIVMSG ".$e->dest." :\002unload\002: ".$1." unloaded.");
                        } else {
                                $e->s("PRIVMSG ".$e->dest." :\002unload\002: ".$1." not found!");
                        }
                # load
                } elsif ($e->data =~ /^\.load ([\w\d]+)$/) {
                        if ($e->robo->{mod}->load_module($1)) {
                                $e->s("PRIVMSG ".$e->dest." :\002load\002: ".$1." loaded.");
                        } else {
                                $e->s("PRIVMSG ".$e->dest." :\002load\002: ".$1." not found!");
                        }
                }
        }
}

# Download, check for errors, and copy modules.
sub down_mod
{
        my ($url, $path, $e, $replace, $title) = @_;

        $url =~ /^.*\/(.+)$/; my $file_name = $1;

        # Check that this module meets requirements to download.
        if (!$file_name =~ /([\w\d\._\-]+\.pm)/) {
                $e->s("PRIVMSG ".$e->dest." :\002".$title."\002: Files should be [a-zA-Z0-9-_].pm!");
                return;
        } elsif (-e $path."modules/".$file_name && !$replace) {
                $e->s("PRIVMSG ".$e->dest." :\002".$title."\002: Module already exists! If you'd like to replace it, use .repmod!");
                return;
        }

        # Download the module.
        my $dl = File::Fetch->new(uri => $url);

        $e->s("PRIVMSG ".$e->dest." :\002".$title."\002: Downloading...");
        if ($dl->fetch(to => $path."modules/temp/")) {
                $e->s("PRIVMSG ".$e->dest." :\002".$title."\002: Downloaded the module! Copying to main modules directory...");

                # Copy temporary download to main modules directory.
                if (copy($path."modules/temp/".$file_name, $path."modules/".$file_name)) {
                        $e->s("PRIVMSG ".$e->dest." :\002".$title."\002: ".$file_name." was successfully copied and loaded!");
                        $file_name =~ /^(.+)\.pm$/;

                        if ($replace) {
                                $e->robo->{mod}->reload_module($1);
                        } else {
                                $e->robo->{mod}->load_module($1);
                        }

                        # Delete the temporary download file.
                        if (!unlink($path."modules/temp/".$file_name)) {
                                $e->s("PRIVMSG ".$e->dest." :\002".$title."\002: ".$path."modules/temp/".$file_name." could not be deleted!");
                        }

                        return;
                # File couldn't be copied.
                } else {
                        $e->s("PRIVMSG ".$e->dest." :\002".$title."\002: ".$file_name." could not be copied! Consult your nearest physician.");

                        # Delete the temporary download file.
                        if (!unlink($path."modules/temp/".$file_name)) {
                                $e->s("PRIVMSG ".$e->dest." :\002".$title."\002: ".$path."modules/temp/".$file_name." could not be deleted!");
                        }

                        return;
                }
        } else {
                $e->s("PRIVMSG ".$e->dest." :\002".$title."\002: Failed to download the module!");
                return;
        }
}

1;
